/*
 * Arc
 * 
 * initial implementation : 31.8.2007
 *
 * Copyright (c) Adam Sida, asida@centrum.cz.
 * All rights reserved.
 * 
 * for license see Petra.Gis.License.txt
 */
using System;
//using System.Collections.Generic;
//using System.Text;
using Petra.Gis.Geometry.Support;
using Petra.Gis.Geometry.Utils;


namespace Petra.Gis.Geometry
{
  /// <summary>
  /// represents arc geometry by given startPoint, endPoint, radius and orientation
  /// note: arc also can be stroked to LineString by Petra.Gis.GeometryUtils.ArcMath class
  /// </summary>
  public class Arc : Curve
  {

    protected CoordinateList _coordinateList;
    protected NormalVector _normalVector;
    protected double _radius;
    protected ReadonlyCoordinate _centerPoint;



    public Arc()
    {
    }




    public Arc(double X1, double Y1, double Z1,double X2, double Y2, double Z2,double I, double J, double K, double Radius)
    {
      //zavolat hlavni konstruktor

      CoordinateList Coords = new CoordinateList(Dimension.dim3D, X1, Y1, Z1, X2, Y2, Z2);
      this.coordList = Coords;

      _normalVector = new NormalVector(I,J,K);
   
      _radius = Radius;
      //centerPoint = getCircleCenter(this.coordList.startPoint, this.coordList.endPoint, dRadius, this.normalVector);
      _valid = true;
    }




    public ReadonlyCoordinate centerPoint
    {
      get
      {
        if (_centerPoint == null)
        {
          Coordinate tmpPt = ArcMath.GetCircleCenter(this.coordList.startPoint, this.coordList.endPoint, _radius, this.normalVector);
          _centerPoint.dX = tmpPt.X;
          _centerPoint.dY = tmpPt.Y;
          _centerPoint.dZ = tmpPt.Z;
        }


        return _centerPoint;
      }
    }




    public override CoordinateList coordList
    {
      get { return _coordinateList; }
      set
      {
        if (coordList.Count != 2)
          throw new ArgumentException("coordList for arc must have exactly 2 points");
        //todo:validate startPoint <> endPoint
        _coordinateList = value;
      }
    }




    public double radius{
      get { return _radius; }
      set { _radius = value; }
    }




    public NormalVector normalVector 
    {
      get { return _normalVector; }
      set { _normalVector = value; }
    }





    internal override BoundingBox getEnvelope()
    {
      double xlo, ylo;
      double xhi, yhi;
      double XS, YS;
      double XE, YE;

      //find smalest X coord
      if (this.coordList.startPoint.X > this.coordList.endPoint.X)
      {
        xhi = this.coordList.startPoint.X;
        xlo = this.coordList.endPoint.X;
      }
      else
      {
        xlo = this.coordList.startPoint.X;
        xhi = this.coordList.endPoint.X;
      }

      //find smalest Y coord
      if (this.coordList.startPoint.Y > this.coordList.endPoint.Y)
      {
        yhi = this.coordList.startPoint.Y;
        ylo = this.coordList.endPoint.Y;
      }
      else
      {
        ylo = this.coordList.startPoint.Y;
        yhi = this.coordList.endPoint.Y;
      }
      //if arc going over more quadrants then min max must change
      XS = (this.coordList.startPoint.X - centerPoint.X) / _radius;
      YS = (this.coordList.startPoint.Y - centerPoint.Y) / _radius;
      XE = (this.coordList.endPoint.X - centerPoint.X) / _radius;
      YE = (this.coordList.endPoint.Y - centerPoint.Y) / _radius;

      if ((YS > 0 && YE < 0) || (YS < 0 && YE > 0))
      {
        if (XS < 0)
          xlo = centerPoint.X - _radius;
        if (XS > 0)
          xhi = centerPoint.X + _radius;
      }
      if ((XS > 0 && XE < 0) || (XS < 0 && XE > 0))
      {
        if (YS < 0)
          ylo = centerPoint.Y - _radius;
        if (YS > 0)
          yhi = centerPoint.Y + _radius;
      }

      _envelope = new BoundingBox(xlo, ylo, xhi, yhi);

      return _envelope;
    }

  }
}
